// SPDX-FileCopyrightText: Copyright 2025-2025 深圳市同心圆网络有限公司
// SPDX-License-Identifier: GPL-3.0-only

package watch_agent_api_impl

import (
	"context"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"math"
	"strings"
	"time"

	"gitcode.com/openseaotter/so_proto_gen_go.git/watch_api"
	"gitcode.com/openseaotter/so_server/storage"
	"github.com/google/uuid"
)

type WatchAgentApiImpl struct {
	watch_api.UnimplementedWatchAgentApiServer
}

func (apiImpl *WatchAgentApiImpl) GetTime(ctx context.Context, req *watch_api.AgentGetTimeRequest) (*watch_api.AgentGetTimeResponse, error) {
	return &watch_api.AgentGetTimeResponse{
		TimeStamp: time.Now().UnixMilli(),
	}, nil
}

func (apiImpl *WatchAgentApiImpl) GetWatchInfo(ctx context.Context, req *watch_api.AgentGetWatchInfoRequest) (*watch_api.AgentGetWatchInfoResponse, error) {
	emptyInfo := &watch_api.WatchInfo{
		FullImageNameList: []string{},
	}

	nowTime := time.Now().UnixMilli()
	if math.Abs(float64(nowTime-req.TimeStamp)) > 60*1000 {
		return &watch_api.AgentGetWatchInfoResponse{
			Code:   watch_api.AgentGetWatchInfoResponse_CODE_WRONG_TIME_STAMP,
			ErrMsg: "时间相差太大",
			Info:   emptyInfo,
		}, nil
	}

	watchInfo, err := storage.WatchInfoDao.Get(ctx, req.WatchId)
	if err != nil {
		return &watch_api.AgentGetWatchInfoResponse{
			Code:   watch_api.AgentGetWatchInfoResponse_CODE_NO_WATCH_INFO,
			ErrMsg: "变更通知配置不存在",
			Info:   emptyInfo,
		}, nil
	}

	sign := apiImpl.genSign(req.TimeStamp, req.RandomStr, watchInfo.Secret)
	if sign != req.Sign {
		return &watch_api.AgentGetWatchInfoResponse{
			Code:   watch_api.AgentGetWatchInfoResponse_CODE_WRONG_SIGN,
			ErrMsg: "错误的签名",
			Info:   emptyInfo,
		}, nil
	}

	return &watch_api.AgentGetWatchInfoResponse{
		Code: watch_api.AgentGetWatchInfoResponse_CODE_OK,
		Info: watchInfo,
	}, nil
}

func (apiImpl *WatchAgentApiImpl) WatchChange(ctx context.Context, req *watch_api.AgentWatchChangeRequest) (*watch_api.AgentWatchChangeResponse, error) {
	defer recover() //防止channel关闭引起的panic

	nowTime := time.Now().UnixMilli()
	if math.Abs(float64(nowTime-req.TimeStamp)) > 60*1000 {
		return &watch_api.AgentWatchChangeResponse{
			Code:   watch_api.AgentWatchChangeResponse_CODE_WRONG_TIME_STAMP,
			ErrMsg: "时间相差太大",
		}, nil
	}

	watchInfo, err := storage.WatchInfoDao.Get(ctx, req.WatchId)
	if err != nil {
		return &watch_api.AgentWatchChangeResponse{
			Code:   watch_api.AgentWatchChangeResponse_CODE_NO_WATCH_INFO,
			ErrMsg: "变更通知配置不存在",
		}, nil
	}

	sign := apiImpl.genSign(req.TimeStamp, req.RandomStr, watchInfo.Secret)
	if sign != req.Sign {
		return &watch_api.AgentWatchChangeResponse{
			Code:   watch_api.AgentWatchChangeResponse_CODE_WRONG_SIGN,
			ErrMsg: "错误的签名",
		}, nil
	}

	recvId := uuid.NewString()
	recvChan := make(chan *storage.ChangeAndCallId, 10)
	defer storage.ChangeNoticeDao.RemoveRecv(req.WatchId, recvId)

	storage.ChangeNoticeDao.AddRecv(req.WatchId, recvId, recvChan)

	changeId := ""
	callId := ""
	select {
	case <-time.After(10 * time.Minute):
	case changeAndCallId := <-recvChan:
		changeId = changeAndCallId.ChangeId
		callId = changeAndCallId.CallId
		break
	}

	return &watch_api.AgentWatchChangeResponse{
		Code:     watch_api.AgentWatchChangeResponse_CODE_OK,
		ChangeId: changeId,
		CallId:   callId,
	}, nil
}

func (apiImpl *WatchAgentApiImpl) genSign(timeStamp int64, randomStr, secret string) string {
	toSignStr := fmt.Sprintf("%d%s%s", timeStamp, randomStr, secret)
	h := sha256.New()
	h.Write([]byte(toSignStr))
	signData := h.Sum(nil)
	return strings.ToLower(hex.EncodeToString(signData))
}

func (apiImpl *WatchAgentApiImpl) GetChange(ctx context.Context, req *watch_api.AgentGetChangeRequest) (*watch_api.AgentGetChangeResponse, error) {
	emptyInfo := &watch_api.ChangeInfo{
		UnChangeUrlList: []string{},
	}

	nowTime := time.Now().UnixMilli()
	if math.Abs(float64(nowTime-req.TimeStamp)) > 60*1000 {
		return &watch_api.AgentGetChangeResponse{
			Code:   watch_api.AgentGetChangeResponse_CODE_WRONG_TIME_STAMP,
			ErrMsg: "时间相差太大",
			Change: emptyInfo,
		}, nil
	}

	watchInfo, err := storage.WatchInfoDao.Get(ctx, req.WatchId)
	if err != nil {
		return &watch_api.AgentGetChangeResponse{
			Code:   watch_api.AgentGetChangeResponse_CODE_NO_WATCH_INFO,
			ErrMsg: "变更通知配置不存在",
			Change: emptyInfo,
		}, nil
	}

	sign := apiImpl.genSign(req.TimeStamp, req.RandomStr, watchInfo.Secret)
	if sign != req.Sign {
		return &watch_api.AgentGetChangeResponse{
			Code:   watch_api.AgentGetChangeResponse_CODE_WRONG_SIGN,
			ErrMsg: "错误的签名",
			Change: emptyInfo,
		}, nil
	}

	changeItem, err := storage.ChangeDao.Get(ctx, req.WatchId, req.ChangeId)
	if err != nil {
		return &watch_api.AgentGetChangeResponse{
			Code:   watch_api.AgentGetChangeResponse_CODE_NO_CHANGE,
			ErrMsg: "变更记录不存在",
			Change: emptyInfo,
		}, nil
	}

	return &watch_api.AgentGetChangeResponse{
		Code:   watch_api.AgentGetChangeResponse_CODE_OK,
		Change: changeItem,
	}, nil
}
